home *** CD-ROM | disk | FTP | other *** search
/ Suzy B Software 2 / Suzy B Software CD-ROM 2 (1994).iso / extras / programm / gemfsc20 / gemfsc20.lzh / GEMFUNCS / OBJTSCRO.C < prev    next >
C/C++ Source or Header  |  1993-03-20  |  22KB  |  595 lines

  1. /*****************************************************************************
  2.  *
  3.  ****************************************************************************/
  4.  
  5. #include "gemfintl.h"
  6.  
  7. #define SCL_DATA_SLL            0x0001
  8. #define SCL_DATA_DLL            0x0002
  9. #define SCL_DRAG_UPDATE         0x0100
  10.  
  11. static OBJECT scroll_tree[] = {
  12.  { -1,  1,  6, G_IBOX,     NONE,       NORMAL,   (_Ob_spec_t)0x00FF1181L,     0x0000, 0x0000, 0x0000, 0x0000},
  13.  
  14.  {  6,  2,  5, G_IBOX,     NONE,       NORMAL,   (_Ob_spec_t)0x00001181L,     0x0000, 0x0000, 0x0000, 0x0000},
  15.  {  3, -1, -1, G_BOXCHAR,  NONE,       NORMAL,   (_Ob_spec_t)0x01FF1181L,     0x0000, 0x0000, 0x0000, 0x0000},
  16.  {  5,  4,  4, G_BOX,      NONE,       NORMAL,   (_Ob_spec_t)0x00FF1191L,     0x0000, 0x0000, 0x0000, 0x0000},
  17.  {  3, -1, -1, G_BOX,      NONE,       NORMAL,   (_Ob_spec_t)0x00FF1181L,     0x0000, 0x0000, 0x0000, 0x0000},
  18.  {  1, -1, -1, G_BOXCHAR,  NONE,       NORMAL,   (_Ob_spec_t)0x02FF1181L,     0x0000, 0x0000, 0x0000, 0x0000},
  19.  
  20.  {  0,  7, 22, G_IBOX,     NONE,       NORMAL,   (_Ob_spec_t)0x00001181L,     0x0000, 0x0000, 0x0000, 0x0000},
  21.  {  8, -1, -1, G_RSTRING,  NONE,       NORMAL,   (_Ob_spec_t)NULL,            0x0000, 0x0000, 0x0000, 0x0001},
  22.  {  9, -1, -1, G_RSTRING,  NONE,       NORMAL,   (_Ob_spec_t)NULL,            0x0000, 0x0001, 0x0000, 0x0001},
  23.  { 10, -1, -1, G_RSTRING,  NONE,       NORMAL,   (_Ob_spec_t)NULL,            0x0000, 0x0002, 0x0000, 0x0001},
  24.  { 11, -1, -1, G_RSTRING,  NONE,       NORMAL,   (_Ob_spec_t)NULL,            0x0000, 0x0003, 0x0000, 0x0001},
  25.  { 12, -1, -1, G_RSTRING,  NONE,       NORMAL,   (_Ob_spec_t)NULL,            0x0000, 0x0004, 0x0000, 0x0001},
  26.  { 13, -1, -1, G_RSTRING,  NONE,       NORMAL,   (_Ob_spec_t)NULL,            0x0000, 0x0005, 0x0000, 0x0001},
  27.  { 14, -1, -1, G_RSTRING,  NONE,       NORMAL,   (_Ob_spec_t)NULL,            0x0000, 0x0006, 0x0000, 0x0001},
  28.  { 15, -1, -1, G_RSTRING,  NONE,       NORMAL,   (_Ob_spec_t)NULL,            0x0000, 0x0007, 0x0000, 0x0001},
  29.  { 16, -1, -1, G_RSTRING,  NONE,       NORMAL,   (_Ob_spec_t)NULL,            0x0000, 0x0008, 0x0000, 0x0001},
  30.  { 17, -1, -1, G_RSTRING,  NONE,       NORMAL,   (_Ob_spec_t)NULL,            0x0000, 0x0009, 0x0000, 0x0001},
  31.  { 18, -1, -1, G_RSTRING,  NONE,       NORMAL,   (_Ob_spec_t)NULL,            0x0000, 0x000A, 0x0000, 0x0001},
  32.  { 19, -1, -1, G_RSTRING,  NONE,       NORMAL,   (_Ob_spec_t)NULL,            0x0000, 0x000B, 0x0000, 0x0001},
  33.  { 20, -1, -1, G_RSTRING,  NONE,       NORMAL,   (_Ob_spec_t)NULL,            0x0000, 0x000C, 0x0000, 0x0001},
  34.  { 21, -1, -1, G_RSTRING,  NONE,       NORMAL,   (_Ob_spec_t)NULL,            0x0000, 0x000D, 0x0000, 0x0001},
  35.  { 22, -1, -1, G_RSTRING,  NONE,       NORMAL,   (_Ob_spec_t)NULL,            0x0000, 0x000E, 0x0000, 0x0001},
  36.  {  6, -1, -1, G_RSTRING,  LASTOB,     NORMAL,   (_Ob_spec_t)NULL,            0x0000, 0x000F, 0x0000, 0x0001}
  37. };
  38.  
  39. #define SCROLL_CONTROLS     1
  40. #define SCROLL_UPARROW      2
  41. #define SCROLL_PAGE         3
  42. #define SCROLL_SLIDER       4
  43. #define SCROLL_DOWNARROW    5
  44. #define DATA_AREA           6
  45. #define FIRST_DATA_LINE     7
  46.  
  47. #define MIN_DATA_CHARS      4
  48. #define MIN_DATA_LINES      5
  49. #define MAX_DATA_LINES     16
  50.  
  51. #define DATA_AREA_WGUTTER       (gl_w2char+gl_w4char)
  52. #define DATA_AREA_HGUTTER       (gl_h2char)
  53.  
  54. #define SCROLL_CONTROL_WIDTH    ((2*gl_wchar) + gl_w2char)
  55. #define SCROLL_ARROW_HEIGHT     (gl_hchar + gl_h4char)
  56.  
  57. #define MIN_SCROLLOBJ_WIDTH     (SCROLL_CONTROL_WIDTH+(MIN_DATA_CHARS*gl_wchar)+(2*DATA_AREA_WGUTTER))
  58.  
  59. #define MIN_SCROLLOBJ_HEIGHT    ((MIN_DATA_LINES*gl_hchar)+(2*DATA_AREA_HGUTTER))
  60. #define MAX_SCROLLOBJ_HEIGHT    ((MAX_DATA_LINES*gl_hchar)+(2*DATA_AREA_HGUTTER))
  61.  
  62.  
  63. /*----------------------------------------------------------------------------
  64.  *
  65.  *--------------------------------------------------------------------------*/
  66.  
  67. typedef struct tscroll_info {
  68.     XUSERBLK xub;                   /* standard XUSERDEF header             */
  69.     void     *datalist;             /* pointer to data to show in scroller  */
  70.     short    numitems;              /* number of items in data list         */
  71.     short    curitem;               /* index of currently selected item     */
  72.     short    topitem;               /* index of item displayed on top line  */
  73.     short    flags;                 /* processing flags                     */
  74.     short    numlines;              /* number of lines in the scroller window*/
  75.     short    statusobj;             /* obj in main tree that shows cur selection*/
  76.     GRECT    dialog_rectangles[7];  /* rectangles describing scroller       */
  77. } TSCROLLINFO;
  78.  
  79. static char nullstr[] = "";         /* empty string for unused data lines   */
  80.  
  81. /*----------------------------------------------------------------------------
  82.  * internal functions...
  83.  *--------------------------------------------------------------------------*/
  84.  
  85. #ifdef GEMFAST_PROTOS
  86.   INTERNAL_VFUNC init_scroll_tree(void);
  87.   INTERNAL_VFUNC update_tree_from_scrollinfo(TSCROLLINFO *pinfo);
  88.   INTERNAL_VFUNC render_scroller(TSCROLLINFO *pinfo, GRECT *cliprect);
  89.   INTERNAL_VFUNC continuous_scroll(TSCROLLINFO *pinfo, short scrollobj, short mx, short my);
  90.   INTERNAL_IFUNC count_items(void *datalist);
  91.   
  92.   static void GCALLBACK udscroll(OBJECT *ptree, short obj, short slidepos, void *udata);
  93.   static XUBT_STATUS GCALLBACK feel_scroller(XUSERBLK *xub, short mx, short my, short clicks);
  94. #endif
  95.  
  96. INTERNAL_VFUNC init_scroll_tree()
  97. /*****************************************************************************
  98.  * one-time init, set y and height of all data lines in scroll tree.
  99.  *  this is essentially in place of doing rsrc_obfix() calls on the tree.
  100.  *  we calc all the xywh values on the fly except for the data lines which
  101.  *  don't move in relation to their parent no matter what else is happening,
  102.  *  so here we do the obfix-style fixup for the data lines.
  103.  ****************************************************************************/
  104. {
  105.     short   hchar = gl_hchar;
  106.     OBJECT *pobj = &scroll_tree[FIRST_DATA_LINE];
  107.  
  108.     do  {
  109.         pobj->ob_y      *= hchar;
  110.         pobj->ob_height *= hchar;
  111.     } while (!((pobj++)->ob_flags & LASTOB));
  112. }
  113.  
  114. INTERNAL_VFUNC update_tree_from_scrollinfo(pinfo)
  115.     TSCROLLINFO *pinfo;
  116. /*****************************************************************************
  117.  * update the scroller dialog tree with values from the specified scroller.
  118.  ****************************************************************************/
  119. {
  120.     short   i;
  121.     short   item;
  122.     short   linewidth;
  123.     char    **strings;
  124.     OBJECT  *pobj;
  125.     short   slidesize;
  126.     short   slidepos;
  127.     long    pixel_range;
  128.  
  129.     /*------------------------------------------------------------------------
  130.      * call lib routine to calc size & position of scroller.  returned
  131.      * values are in the range 1-1000, or -1 for minimum-sized slider.
  132.      *----------------------------------------------------------------------*/
  133.  
  134.     wc_scroll_calc(pinfo->topitem, pinfo->numitems, pinfo->numlines,
  135.         &slidesize, &slidepos);
  136.  
  137.     /*------------------------------------------------------------------------
  138.      * translate position and size into actual x/y/w/h values.
  139.      *----------------------------------------------------------------------*/
  140.  
  141.     pixel_range = pinfo->dialog_rectangles[SCROLL_PAGE].g_h;
  142.  
  143.     slidesize = (short)((pixel_range * slidesize) / 1000L);
  144.  
  145.     if (slidesize < gl_hchar) {
  146.         slidesize = gl_hchar;
  147.     }
  148.  
  149.     slidepos = (short)(((pixel_range-slidesize) * slidepos) / 1000L);
  150.  
  151.     pinfo->dialog_rectangles[SCROLL_SLIDER].g_y = slidepos;
  152.     pinfo->dialog_rectangles[SCROLL_SLIDER].g_h = slidesize;
  153.  
  154.     /*------------------------------------------------------------------------
  155.      * set the dialog's controlling rectangles to scroller's values.
  156.      *----------------------------------------------------------------------*/
  157.  
  158.     pobj = scroll_tree;
  159.  
  160.     for (i = 0; i < Array_els(pinfo->dialog_rectangles); ++i) {
  161.         *(GRECT *)&pobj->ob_x = pinfo->dialog_rectangles[i];
  162.         ++pobj;
  163.     }
  164.  
  165.     /*------------------------------------------------------------------------
  166.      * set string pointers in the visible area of the scroller dialog.
  167.      *----------------------------------------------------------------------*/
  168.  
  169.     strings   = (char **)pinfo->datalist;
  170.     item      = pinfo->topitem;
  171.     linewidth = pinfo->dialog_rectangles[DATA_AREA].g_w;
  172.  
  173.     for (i = 0; i < MAX_DATA_LINES; ++i) {
  174.         if (i >= pinfo->numlines) {         /* line isn't in visible area   */
  175.             pobj->ob_flags |= HIDETREE;     /* of scroller, hide it.        */
  176.         } else {
  177.             pobj->ob_flags &= ~HIDETREE;    /* line is visible, unhide it.  */
  178.             pobj->ob_width  = linewidth;    /* set line object width.       */
  179.             if (item >= pinfo->numitems) {  /* if we're out of lines (short */
  180.                 pobj->ob_spec = (_Ob_spec_t)nullstr; /* data list), show an empty line.*/
  181.             } else {
  182.                 pobj->ob_spec = (_Ob_spec_t)(strings[item]);
  183.             }
  184.             pobj->ob_state = (item == pinfo->curitem) ? SELECTED : NORMAL;
  185.             ++item;
  186.         }
  187.         ++pobj;
  188.     }
  189. }
  190.  
  191. INTERNAL_VFUNC render_scroller(pinfo, cliprect)
  192.     TSCROLLINFO *pinfo;
  193.     GRECT       *cliprect;
  194. /*****************************************************************************
  195.  * update the scroller visuals (controls, data area), then paint it.
  196.  ****************************************************************************/
  197. {
  198.     update_tree_from_scrollinfo(pinfo);
  199.     obj__draw(scroll_tree, ROOT, MAX_DEPTH, cliprect);
  200. }
  201.  
  202. static long GCALLBACK see_scroller(pb)
  203.     XPARMBLK *pb;
  204. /*****************************************************************************
  205.  * USERDEF drawing routine for scroller objects.
  206.  ****************************************************************************/
  207. {
  208.     TSCROLLINFO *pinfo = (TSCROLLINFO *)pb->pub;
  209.  
  210.     pinfo->dialog_rectangles[0].g_x = pb->drawrect.g_x;
  211.     pinfo->dialog_rectangles[0].g_y = pb->drawrect.g_y;
  212.  
  213.     render_scroller(pinfo, &pb->cliprect);
  214.  
  215.     return 0;
  216. }
  217.  
  218. static void GCALLBACK udscroll(ptree, obj, slidepos, udata)
  219.     OBJECT  *ptree;
  220.     short   obj;
  221.     short   slidepos;
  222.     void    *udata;
  223. /*****************************************************************************
  224.  * the callback for grf_udslidebox() -- update window based on slider
  225.  ****************************************************************************/
  226. {
  227.     TSCROLLINFO *pinfo = udata;
  228.  
  229.     if (slidepos > 2000) {
  230.         slidepos -= 2000;
  231.     } else if (slidepos > 1000) {
  232.         slidepos -= 1000;
  233.     }
  234.  
  235.     pinfo->topitem = (short)((slidepos * (pinfo->numitems - pinfo->numlines)) / 1000L);
  236.     render_scroller(pinfo, &gl_rwdesk);
  237.  
  238. }
  239.  
  240. INTERNAL_VFUNC continuous_scroll(pinfo, scrollobj, mx, my)
  241.     TSCROLLINFO *pinfo;
  242.     short       scrollobj;
  243.     short       mx;
  244.     short       my;
  245. /*****************************************************************************
  246.  * continuously scroll the scroller object until mouse button released.
  247.  ****************************************************************************/
  248. {
  249.     short mb;
  250.     short slidey;
  251.     short dmy;
  252.     short scrollamt;
  253.     short newtop;
  254.  
  255.     if (scrollobj == SCROLL_SLIDER) {
  256.         grf_udslidebox(scroll_tree, SCROLL_SLIDER, TRUE, udscroll, pinfo);
  257.         return;
  258.     } else {
  259.         switch (scrollobj) {
  260.           case SCROLL_UPARROW:
  261.             scrollamt = -1;
  262.             break;
  263.           case SCROLL_DOWNARROW:
  264.             scrollamt = 1;
  265.             break;
  266.           case SCROLL_PAGE:
  267.             objc_offset(scroll_tree, SCROLL_SLIDER, &dmy, &slidey);
  268.             if (my < slidey) {
  269.                 scrollamt = -(pinfo->numlines);
  270.             } else {
  271.                 scrollamt = pinfo->numlines;
  272.             }
  273.             break;
  274.         }
  275.     }
  276.  
  277.     do  {
  278.         newtop = pinfo->topitem + scrollamt;
  279.         if ((newtop + pinfo->numlines) > pinfo->numitems) {
  280.             newtop = pinfo->numitems - pinfo->numlines;
  281.         }
  282.         if (newtop < 0) {
  283.             newtop = 0;
  284.         }
  285.         if (pinfo->topitem != newtop || scrollamt == 0) {
  286.             pinfo->topitem = newtop;
  287.             render_scroller(pinfo, &gl_rwdesk);
  288.         }
  289.         graf_mkstate(&dmy, &dmy, &mb, &dmy);
  290.     } while (mb);
  291. }
  292.  
  293. static XUBT_STATUS GCALLBACK feel_scroller(xub, mx, my, clicks)
  294.     XUSERBLK *xub;
  295.     short    mx;
  296.     short    my;
  297.     short    clicks;
  298. /*****************************************************************************
  299.  * routine to handle a click on a scroller object.
  300.  ****************************************************************************/
  301. {
  302.     short        clickobj;
  303.     TSCROLLINFO *pinfo = (TSCROLLINFO *)xub;
  304.     XUBT_STATUS  status;
  305.  
  306.     update_tree_from_scrollinfo(pinfo);
  307.     clickobj = objc_find(scroll_tree, ROOT, MAX_DEPTH, mx, my);
  308.  
  309.     if (clickobj <= ROOT || clickobj == DATA_AREA) {
  310.         status = XUBT_NONE;
  311.     } else if (DATA_AREA == obj_parent(scroll_tree, clickobj)) {
  312.         pinfo->curitem = pinfo->topitem + (clickobj - FIRST_DATA_LINE);
  313.         pinfo->xub.ob_spec = scroll_tree[clickobj].ob_spec;
  314.         update_tree_from_scrollinfo(pinfo);
  315.         obj__draw(scroll_tree, DATA_AREA, MAX_DEPTH, &gl_rwdesk);
  316.         if (pinfo->statusobj != NO_OBJECT) {
  317.             rsc_sstrings(xub->parent_tree, pinfo->statusobj, (char *)pinfo->xub.ob_spec, -1);
  318.             obj__draw(xub->parent_tree, pinfo->statusobj, MAX_DEPTH, &gl_rwdesk);
  319.         }
  320.         status = XUBT_VALUE;
  321.         if (clicks > 1) {
  322.             status |= XUBT_DCEXIT;
  323.         }
  324.         evn_wbutton(EVN_BUTTONUP);
  325.     } else {
  326.         continuous_scroll(pinfo, clickobj, mx, my);
  327.         status = XUBT_VISUAL;
  328.     }
  329.  
  330.     return status;
  331. }
  332.  
  333. INTERNAL_IFUNC count_items(datalist)
  334.     void *datalist;
  335. /*****************************************************************************
  336.  *
  337.  ****************************************************************************/
  338. {
  339.     char **strings;
  340.     short numitems = 0;
  341.  
  342.     for (strings = (char **)datalist; *strings != NULL; ++strings) {
  343.         ++numitems;
  344.     }
  345.  
  346.     return numitems;
  347. }
  348.  
  349. /*----------------------------------------------------------------------------
  350.  * public functions...
  351.  *--------------------------------------------------------------------------*/
  352.  
  353. short obj_make_tscroll(ptree, obj, statusobj)
  354.     OBJECT *ptree;
  355.     short   obj;
  356.     short   statusobj;
  357. /*****************************************************************************
  358.  *
  359.  ****************************************************************************/
  360. {
  361.     register OBJECT      *pobj = &ptree[obj];
  362.     register TSCROLLINFO *pinfo;
  363.  
  364.     if (scroll_tree[FIRST_DATA_LINE].ob_height == 1) {
  365.         init_scroll_tree(); /* do one-time init if not done already         */
  366.     }
  367.  
  368.     /*------------------------------------------------------------------------
  369.      * validate parms.
  370.      *----------------------------------------------------------------------*/
  371.  
  372.     if (0 == apl_vshared()) {
  373.         return gfErr_vdi_handle;
  374.     }
  375.  
  376.     if (pobj->ob_width < MIN_SCROLLOBJ_WIDTH ||
  377.         pobj->ob_height < MIN_SCROLLOBJ_HEIGHT) {
  378.         return gfErr_object_too_small;
  379.     }
  380.  
  381.     if (pobj->ob_height > MAX_SCROLLOBJ_HEIGHT) {
  382.         return gfErr_object_too_big;
  383.     }
  384.  
  385.     /*------------------------------------------------------------------------
  386.      * If the object has already been made into a G_TSCROLL extended object,
  387.      * just get its pointer, else make it into such an object.
  388.      *----------------------------------------------------------------------*/
  389.  
  390.     if ((pobj->ob_type & 0x00FF) == G_USERDEF) {
  391.         pinfo = (TSCROLLINFO *)pobj->_Ob_spec;
  392.         if (pinfo->xub.ob_type != G_TSCROLL) {
  393.             return gfErr_wrong_type;
  394.         }
  395.     } else {
  396.         if (NULL == (pinfo = apl_malloc((long)sizeof(*pinfo)))) {
  397.             return gfErr_no_memory;
  398.         }
  399.         obj_mxuserdef(ptree, obj, &pinfo->xub, see_scroller, feel_scroller, (long)sizeof(*pinfo));
  400.         pinfo->xub.ob_type = G_TSCROLL;
  401.         pinfo->xub.ob_spec = (_Ob_spec_t)NULL;
  402.     }
  403.  
  404.     pinfo->datalist  = NULL;
  405.     pinfo->numitems  = 0;
  406.     pinfo->curitem   = NO_OBJECT;
  407.     pinfo->topitem   = 0;
  408.     pinfo->flags     = 0;
  409.     pinfo->statusobj = statusobj;
  410.     pinfo->numlines  = (pobj->ob_height - (2 * DATA_AREA_HGUTTER)) / gl_hchar;
  411.  
  412.     if (statusobj != NO_OBJECT) {
  413.         rsc_sstrings(ptree, statusobj, nullstr, -1);
  414.     }
  415.  
  416.     /*------------------------------------------------------------------------
  417.      * build the rectangles describing the on-screen scroller.
  418.      *----------------------------------------------------------------------*/
  419.  
  420. #define SetRect(idx, x, y, w, h)            \
  421.     pinfo->dialog_rectangles[idx].g_x = x;  \
  422.     pinfo->dialog_rectangles[idx].g_y = y;  \
  423.     pinfo->dialog_rectangles[idx].g_w = w;  \
  424.     pinfo->dialog_rectangles[idx].g_h = h;
  425.  
  426.     SetRect(ROOT,
  427.         pobj->ob_x,
  428.         pobj->ob_y,
  429.         pobj->ob_width,
  430.         pobj->ob_height);
  431.  
  432.     SetRect(SCROLL_CONTROLS,
  433.         (pobj->ob_width - SCROLL_CONTROL_WIDTH),
  434.         0,
  435.         SCROLL_CONTROL_WIDTH,
  436.         pobj->ob_height);
  437.  
  438.     SetRect(SCROLL_UPARROW,
  439.         0,
  440.         0,
  441.         SCROLL_CONTROL_WIDTH,
  442.         SCROLL_ARROW_HEIGHT);
  443.  
  444.     SetRect(SCROLL_PAGE,
  445.         0,
  446.         SCROLL_ARROW_HEIGHT,
  447.         SCROLL_CONTROL_WIDTH,
  448.         (pobj->ob_height - 2 * SCROLL_ARROW_HEIGHT));
  449.  
  450.     SetRect(SCROLL_SLIDER,
  451.         0,
  452.         0,
  453.         SCROLL_CONTROL_WIDTH,
  454.         1);
  455.  
  456.     SetRect(SCROLL_DOWNARROW,
  457.         0,
  458.         (SCROLL_ARROW_HEIGHT + pinfo->dialog_rectangles[SCROLL_PAGE].g_h),
  459.         SCROLL_CONTROL_WIDTH,
  460.         SCROLL_ARROW_HEIGHT);
  461.  
  462.     SetRect(DATA_AREA,
  463.         DATA_AREA_WGUTTER,
  464.         DATA_AREA_HGUTTER,
  465.         (pobj->ob_width - SCROLL_CONTROL_WIDTH - (2 * DATA_AREA_WGUTTER)),
  466.         (pobj->ob_height - (2 * DATA_AREA_HGUTTER)));
  467.  
  468. #undef SetRect
  469.  
  470.     return 0;
  471.  
  472. }
  473.  
  474. void obj_set_tscroll(ptree, obj, datalist, numitems, curitem, topitem)
  475.     OBJECT *ptree;
  476.     short   obj;
  477.     void    *datalist;
  478.     short   numitems;
  479.     short   curitem;
  480.     short   topitem;
  481. /*****************************************************************************
  482.  *
  483.  ****************************************************************************/
  484. {
  485.     TSCROLLINFO *pinfo;
  486.  
  487.     if (ptree[obj].ob_flags & INDIRECT) {
  488.         pinfo = *(TSCROLLINFO **)ptree[obj].ob_spec;
  489.     } else {
  490.         pinfo = (TSCROLLINFO *)ptree[obj].ob_spec;
  491.     }
  492.  
  493.     if ((ptree[obj].ob_type & 0x00FF) != G_USERDEF) {
  494.         return;
  495.     }
  496.  
  497.     if (pinfo->xub.ob_type != G_TSCROLL) {
  498.         return;
  499.     }
  500.  
  501.     /*------------------------------------------------------------------------
  502.      * fill in the details in the scrollinfo structure...
  503.      *----------------------------------------------------------------------*/
  504.  
  505.     if (datalist != NULL) {
  506.         pinfo->datalist = datalist;
  507.         pinfo->curitem  = NO_OBJECT;
  508.         pinfo->topitem  = 0;
  509.         if (numitems < 0) {
  510.             numitems = count_items(datalist);
  511.         }
  512.     }
  513.  
  514.     if (numitems >= 0) {
  515.         pinfo->numitems = numitems;
  516.     }
  517.  
  518.     if (curitem >= NO_OBJECT) {
  519.         if (curitem < pinfo->numitems) {
  520.             pinfo->curitem = curitem;
  521.         } else {
  522.             pinfo->curitem = NO_OBJECT;
  523.         }
  524.     }
  525.  
  526.     if (topitem >= 0) {
  527.         if (topitem < pinfo->numitems) {
  528.             pinfo->topitem = topitem;
  529.         } else {
  530.             pinfo->topitem = 0;
  531.         }
  532.     }
  533.  
  534.     if (pinfo->datalist == NULL || pinfo->curitem == NO_OBJECT) {
  535.         pinfo->xub.ob_spec = (_Ob_spec_t)NULL;
  536.     } else {
  537.         void **items = (void **)pinfo->datalist;
  538.         pinfo->xub.ob_spec = (_Ob_spec_t)items[pinfo->curitem];
  539.     }
  540.  
  541.     if (pinfo->statusobj != NO_OBJECT) {
  542.         char *curstr;
  543.         if (pinfo->curitem == NO_OBJECT) {
  544.             curstr = nullstr;
  545.         } else {
  546.             curstr = (char *)pinfo->xub.ob_spec;
  547.         }
  548.         rsc_sstrings(ptree, pinfo->statusobj, curstr, -1);
  549.     }
  550.  
  551. }
  552.  
  553. short obj_get_tscroll(ptree, obj, curstring, curitem, topitem)
  554.     OBJECT *ptree;
  555.     short   obj;
  556.     char    **curstring;
  557.     short   *curitem;
  558.     short   *topitem;
  559. /*****************************************************************************
  560.  *
  561.  ****************************************************************************/
  562. {
  563.     TSCROLLINFO  *pinfo;
  564.  
  565.     if (ptree[obj].ob_flags & INDIRECT) {
  566.         pinfo = *(TSCROLLINFO **)ptree[obj].ob_spec;
  567.     } else {
  568.         pinfo = (TSCROLLINFO *)ptree[obj].ob_spec;
  569.     }
  570.  
  571.     if ((ptree[obj].ob_type & 0x00FF) != G_USERDEF) {
  572.         return NO_OBJECT;
  573.     }
  574.  
  575.     if (pinfo->xub.ob_type != G_TSCROLL) {
  576.         return NO_OBJECT;
  577.     }
  578.  
  579.     if (topitem != NULL) {
  580.         *topitem = pinfo->topitem;
  581.     }
  582.  
  583.     if (curstring != NULL) {
  584.         *curstring = (char*)pinfo->xub.ob_spec;
  585.     }
  586.  
  587.     if (curitem != NULL) {
  588.         *curitem = pinfo->curitem;
  589.     }
  590.  
  591.     return pinfo->curitem;
  592. }
  593.  
  594.  
  595.